package com.distribution.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.distribution.common.core.domain.entity.SysUser;
import com.distribution.common.exception.ServiceException;
import com.distribution.common.utils.StringUtils;
import com.distribution.system.config.FuluConfig;
import com.distribution.system.domain.dto.AuthInfoDto;
import com.distribution.system.domain.dto.AuthInfoListDto;
import com.distribution.system.domain.entity.FuluUploadPeople;
import com.distribution.system.domain.req.ReqResult;
import com.distribution.system.mapper.FuluUploadPeopleMapper;
import com.distribution.system.mapper.SysUserMapper;
import com.distribution.system.service.FuluUploadPeopleService;
import com.distribution.system.service.ISysUserService;
import com.distribution.system.utils.http.HttpRequestUtils;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
import static com.distribution.common.utils.SecurityUtils.getUserId;
import static com.distribution.common.utils.SecurityUtils.getUsername;

/**
 * 表服务实现类
 */
@Service("fuluUploadPeopleService")
@Slf4j
public class FuluUploadPeopleServiceImpl extends ServiceImpl<FuluUploadPeopleMapper, FuluUploadPeople> implements FuluUploadPeopleService {
    private static final Logger agentAuthLog = LoggerFactory.getLogger("agentAuthLog");
    @Resource
    FuluConfig fuluConfig;
    @Resource
    ISysUserService iSysUserService;
    @Resource
    SysUserMapper sysUserMapper;

    @Override
    public ReqResult updateAuthInfoById(@Validated AuthInfoDto authInfoDto) {
        log.info("修改认证信息 => {}", authInfoDto);
        agentAuthLog.info("修改认证信息 => {}", authInfoDto);
        SysUser sysUser = sysUserMapper.selectUserByUserName(authInfoDto.getAccount());
        if (sysUser == null) return ReqResult.error("用户不存在");
        // 如果用户ID被绑定则解绑
        List<FuluUploadPeople> fuluUploadPeopleList = lambdaQuery().eq(FuluUploadPeople::getUserId, sysUser.getUserId()).list();
        if (!fuluUploadPeopleList.isEmpty()){
            fuluUploadPeopleList.forEach(f -> lambdaUpdate().eq(FuluUploadPeople::getUserId, f.getUserId()).set(FuluUploadPeople::getUserId, null).update());
        }
        lambdaUpdate().eq(FuluUploadPeople::getId, authInfoDto.getId())
                .set(FuluUploadPeople::getAccount, sysUser.getUserName())
                .set(FuluUploadPeople::getNickName, sysUser.getNickName())
                .set(FuluUploadPeople::getUserId, sysUser.getUserId())
                .set(FuluUploadPeople::getUserName, authInfoDto.getUserName())
                .set(FuluUploadPeople::getIdCard, authInfoDto.getIdCard())
                .set(FuluUploadPeople::getMobile, authInfoDto.getMobile())
                .set(!StringUtils.isEmpty(authInfoDto.getSignStatus()), FuluUploadPeople::getSignStatus, authInfoDto.getSignStatus())
                .update();
        return ReqResult.success();
    }

    @Override
    public List<FuluUploadPeople> getFuluUploadPepleInfoList(AuthInfoListDto authInfoListDto) {
        LambdaQueryWrapper<FuluUploadPeople> queryWrapper = new LambdaQueryWrapper<>();
        if (!StringUtils.isEmpty(authInfoListDto.getAccount())) {
            SysUser sysUser = sysUserMapper.selectUserByUserName(authInfoListDto.getAccount());
            if (sysUser == null) throw new ServiceException("查询不到该账号信息");
            queryWrapper.eq(FuluUploadPeople::getUserId, sysUser.getUserId());
        }
        if (!StringUtils.isEmpty(authInfoListDto.getUserName())) {
            queryWrapper.eq(FuluUploadPeople::getUserName, authInfoListDto.getUserName());
        }
        if (!StringUtils.isEmpty(authInfoListDto.getIdCard())) {
            queryWrapper.eq(FuluUploadPeople::getIdCard, authInfoListDto.getIdCard());
        }
        if (!StringUtils.isEmpty(authInfoListDto.getMobile())) {
            queryWrapper.eq(FuluUploadPeople::getMobile, authInfoListDto.getMobile());
        }
        if (!StringUtils.isEmpty(authInfoListDto.getSignStatus())) {
            queryWrapper.eq(FuluUploadPeople::getSignStatus, authInfoListDto.getSignStatus());
        }
        queryWrapper.eq(FuluUploadPeople::getDeleteFlag, 0);
        queryWrapper.orderByDesc(FuluUploadPeople::getCreateTime);
        return list(queryWrapper);
    }

    @Override
    public void fuluUploadPeople(FuluUploadPeople fuluUploadPeople) {
        log.info("添加认证信息 => {}", fuluUploadPeople);
        agentAuthLog.info("添加认证信息 => {}", fuluUploadPeople);
        if (StringUtils.isEmpty(fuluUploadPeople.getIdCard())) {
            throw new ServiceException("身份证号不能为空");
        }
        if (StringUtils.isEmpty(fuluUploadPeople.getUserName())) {
            throw new ServiceException("姓名不能为空");
        }
        if (StringUtils.isEmpty(fuluUploadPeople.getMobile())) {
            throw new ServiceException("手机号不能为空");
        }
        FuluUploadPeople one = lambdaQuery().eq(FuluUploadPeople::getIdCard, fuluUploadPeople.getIdCard())
                .eq(FuluUploadPeople::getUserName, fuluUploadPeople.getUserName()).eq(FuluUploadPeople::getDeleteFlag, 0).one();
        if (one != null) {
            if (fuluUploadPeople.getUserId() != null && !fuluUploadPeople.getUserId().equals(one.getUserId())) {
                SysUser sysUser = iSysUserService.selectUserById(fuluUploadPeople.getUserId());
                throw new ServiceException("该认证信息被" + sysUser.getUserName() + "代理占用! 无法修改");
            }
            one.setMobile(fuluUploadPeople.getMobile());
            one.setUpdateTime(new Date());
            updateById(one);
            return;
        }
        //请求付穗第三方接口
        Map<String, String> paramsMap = new HashMap<>(16);
        paramsMap.put("idCard",fuluUploadPeople.getIdCard());
        paramsMap.put("taskNo",fuluConfig.getTaskNo());
        paramsMap.put("mobile",fuluUploadPeople.getMobile());
        paramsMap.put("userName",fuluUploadPeople.getUserName());
        String param = paramPackage(paramsMap);
        String res = null;
        try {
            res = HttpRequestUtils.sendPost(fuluConfig.getAddress() + fuluConfig.getUploadPeople(), param);
        } catch (Exception e) {
            log.info("添加认证信息时向三方发送请求时发生异常{}", e.getMessage());
            agentAuthLog.info("添加认证信息时向三方发送请求时发生异常{}", e.getMessage());
        }
        JSONObject jsonObject = JSONObject.parseObject(res);
        Integer code = jsonObject.getInteger("code");
        //请求失败
        if (code != 0) {
            throw new ServiceException(jsonObject.getString("msg"));
        } else {//请求成功
            Long userId = getUserId();
            SysUser currentSysUser = sysUserMapper.selectUserById(userId);
            /*if (fuluUploadPeople.getUserId() != null) {
                userId = fuluUploadPeople.getUserId();
                fuluUploadPeople.setAccount(currentSysUser.getUserName());
                fuluUploadPeople.setNickName(currentSysUser.getNickName());
            }*/
            lambdaUpdate().set(FuluUploadPeople::getDeleteFlag,1).eq(FuluUploadPeople::getUserId,userId).update();
            String username = getUsername();
            JSONObject data = jsonObject.getJSONObject("data");
            String peopleId = data.getString("peopleId");
            String signUrl = data.getString("signUrl");
            Integer signStatus = data.getInteger("signStatus");
            String failReason = data.getString("failReason");
            String outBizNo = data.getString("outBizNo");
            String idCardFrontUrl = data.getString("idCardFrontUrl");
            String idCardBackUrl = data.getString("idCardBackUrl");
            String livingImageUrl = data.getString("livingImageUrl");
            fuluUploadPeople.setPeopleId(peopleId);
            fuluUploadPeople.setSignUrl(signUrl);
            fuluUploadPeople.setUserId(userId);
            fuluUploadPeople.setAccount(currentSysUser.getUserName());
            fuluUploadPeople.setNickName(currentSysUser.getNickName());
            fuluUploadPeople.setSignStatus(String.valueOf(signStatus));
            fuluUploadPeople.setFailReason(failReason);
            fuluUploadPeople.setTaskNo(fuluConfig.getTaskNo());
            fuluUploadPeople.setOutBizNo(outBizNo);
            fuluUploadPeople.setIdCardFrontUrl(idCardFrontUrl);
            fuluUploadPeople.setIdCardBackUrl(idCardBackUrl);
            fuluUploadPeople.setLivingImageUrl(livingImageUrl);
            fuluUploadPeople.setCreateUserId(userId);
            fuluUploadPeople.setCreateUserName(username);
            save(fuluUploadPeople);
        }
    }

    @Override
    public String queryPeople(FuluUploadPeople fuluUploadPeople) {
        Map<String, String> paramsMap = new HashMap<>();
        paramsMap.put("peopleId",fuluUploadPeople.getPeopleId());
        String param = paramPackage(paramsMap);
        String res = null;
        try {
            res = HttpRequestUtils.sendPost(fuluConfig.getAddress() + fuluConfig.getQueryPeople(), param);
        } catch (Exception e) {
            log.info("向三方查询认证信息时发生异常{}", e.getMessage());
            agentAuthLog.info("向三方查询认证信息时发生异常{}", e.getMessage());
        }
        JSONObject jsonObject = JSONObject.parseObject(res);
        Integer code = jsonObject.getInteger("code");
        if (code != 0) {
            throw new ServiceException(jsonObject.getString("msg"));
        } else {
            JSONObject data = jsonObject.getJSONObject("data");
            String peopleId = data.getString("peopleId");
            Integer signStatus = data.getInteger("signStatus");
            String failReason = data.getString("failReason");
            lambdaUpdate().set(FuluUploadPeople::getSignStatus,signStatus)
                    .set(FuluUploadPeople::getFailReason,failReason)
                    .set(FuluUploadPeople::getUpdateTime,new Date())
                    .eq(FuluUploadPeople::getPeopleId,peopleId).update();
        }
        return res;
    }

    @Override
    public void fuluMessage(JSONObject jsonObject) {
        JSONObject bizContent = jsonObject.getJSONObject("bizContent");
        Integer signStatus = bizContent.getInteger("signStatus");
        String peopleId = bizContent.getString("peopleId");
        lambdaUpdate().set(FuluUploadPeople::getSignStatus,signStatus)
                .set(FuluUploadPeople::getUpdateTime,new Date())
                .eq(FuluUploadPeople::getPeopleId,peopleId).update();
    }

    @Override
    public FuluUploadPeople selectPeople(Long userId) {
        if (userId == null) {
            userId = getUserId();
        }
        FuluUploadPeople one = lambdaQuery().eq(FuluUploadPeople::getUserId, userId).eq(FuluUploadPeople::getDeleteFlag, 0).one();
        if (one != null && ("0".equals(String.valueOf(one.getSignStatus())) || "2".equals(String.valueOf(one.getSignStatus())))) {
            queryPeople(one);
            return lambdaQuery().eq(FuluUploadPeople::getUserId, userId).eq(FuluUploadPeople::getDeleteFlag, 0).one();
        }
        return one;
    }

    public String paramPackage(Map<String, String> paramsMap) {
        String json = new Gson().toJson(paramsMap);
        long time = System.currentTimeMillis();
        String currentTimeMillis = String.valueOf(time);
        // 长度最大32位
        String nonce = generate32BitUUID();
        // 固定参数
        Map<String, String> param = new HashMap<>();
        param.put("appId", fuluConfig.getAppId());
        param.put("nonce", nonce);
        param.put("timestamp", currentTimeMillis);
        param.put("bizContent", json);
        String sign = null;
        String sortParams = sortParams(param);
        //System.out.println("排序字段:" + sortParams);
        String sb = splice(fuluConfig.getAppSecret(), sortParams);
        //System.out.println("加签名字符串排序字段 :" + sb);
        try {
            sign = sign(sb, currentTimeMillis, fuluConfig.getAppSecret());
        } catch (Exception e) {
            e.printStackTrace();
        }
        param.put("sign", sign);
        //System.out.println("签名 : " + sign);
        return new Gson().toJson(param);

    }


    public static String generate32BitUUID() {
        UUID uuid = UUID.randomUUID();
        String uuidString = uuid.toString();
        // 去掉'-'分隔符
        return uuidString.replace("-", "");
    }
    /**
     * 将map排序为字符串
     */
    public static String sortParams(Map<String, String> parameters) {
        if (parameters.isEmpty()) {
            return null;
        }
        List<String> removeKeys = new ArrayList<>();
        for (Map.Entry<String, String> entry : parameters.entrySet()) {
            if (isBlank(entry.getValue())) {
                removeKeys.add(entry.getKey());
            }
        }

        for (String key : removeKeys) {
            parameters.remove(key);
        }
        StringBuilder stringBuilder = new StringBuilder();
        SortedMap<String, String> paramMap = new TreeMap<>(parameters);
        int index = 0;
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            stringBuilder.append(entry.getKey()).append("=").append(entry.getValue());
            index++;
            if (index != parameters.size()) {
                stringBuilder.append("&");
            }
        }
        return stringBuilder.toString();
    }


    public static byte[] hmac256(byte[] key, String msg) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
        mac.init(secretKeySpec);
        return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8));
    }

    public static String sha256Hex(String s) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] d = md.digest(s.getBytes(StandardCharsets.UTF_8));
        return DatatypeConverter.printHexBinary(d).toLowerCase();
    }

    /**
     * 拼接appSecret和
     * @param content sortParams
     */
    public static String splice(String appSecret, String content) {
        if (appSecret == null ) {
            return content;
        }
        if (appSecret.length() < 10){
            return "";
        }

        // 截取前5位和后5位
        String front = appSecret.substring(0, 5);
        String back = appSecret.substring(appSecret.length() - 5);

        return front + content + back;
    }


    /**
     * @param sortParam 排序map后得到的字符串
     * @param timestamp 时间戳
     * @param appSecret 应用秘钥
     * @return 签名值
     * @throws Exception 异常
     */
    public static String sign(String sortParam, String timestamp, String appSecret) throws Exception {
        //将排序后字符串转为sha256Hex
        String signText = sha256Hex(sortParam);
        System.out.println(signText);
        //计算签名
        byte[] secretSigning = hmac256((appSecret).getBytes(StandardCharsets.UTF_8), timestamp);
        //计算后得到签名
        return DatatypeConverter.printHexBinary(hmac256(secretSigning, signText)).toLowerCase();
    }

    public static boolean isBlank(CharSequence str) {
        int length;

        if ((str == null) || ((length = str.length()) == 0)) {
            return true;
        }

        for (int i = 0; i < length; i++) {
            // 只要有一个非空字符即为非空字符串
            if (!isBlankChar(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    public static boolean isBlankChar(int c) {
        return Character.isWhitespace(c)
                || Character.isSpaceChar(c)
                || c == '\ufeff'
                || c == '\u202a'
                || c == '\u0000';
    }
}
